#include <iostream>
#include <string>
#include<set>
#include "Log.hpp"
#include "InetAddr.hpp"
class Command
{
public:
    Command() {
        _safe_command.insert("ls");
        _safe_command.insert("toush");
        _safe_command.insert("pwd");
        _safe_command.insert("whoami");
        _safe_command.insert("which");

    }
    ~Command() {}
    bool SafeCheck(const std::string &cmdstr)
    {
        for(auto &cmd:_safe_command)
        {
            if(strncmp(cmd.c_str(),cmdstr.c_str(),cmd.size())==0)
            {
                return true;
            }
        }
        return false;

    }

    // 将命令的结果输出
    std::string Excute(const std::string cmdstr)
    {
        std::string result;
        FILE * fp=popen(cmdstr.c_str(),"r");
        if(fp)
        {
            char line[1024];
            while(fgets(line,sizeof(line),fp))
            {
                result+=line;
            }
            return result;

        }
        return "execute error";
    }
    void HandlerCommand(int sockfd, InetAddr addr)
    {
        // 长服务
        while (true)
        {
            // 这里是流字节流  tcp 可以直接使用流的接口来使用
            char inbuffer[1024];
            // ssize_t n = ::read(sockfd, inbuffer, sizeof(inbuffer) - 1); // 店内的人元就像是一个管文件，从中读取
            ssize_t n = ::recv(sockfd, inbuffer, sizeof(inbuffer) - 1,0); // 店内的人元就像是一个管文件，从中读取
            // 这里建立了链接就像管道中读取
            if (n > 0) // 成功夺取
            {
                inbuffer[n]=0;
                LOG(INFO,"get command from client %s,command: %s\n",addr.AddrStr().c_str(),inbuffer);
                //处理数据将命令执行并将结果输出
                std::string result;
                if(SafeCheck(inbuffer))
                result=Excute(inbuffer);
                // ::wirte(sockfd, echo_string.c_str(), echo_string.size());
                ::send(sockfd, result.c_str(), result.size(),0);
            }
            else if (n == 0) // 发送方下线了
            {
                LOG(INFO, "client %s quit\n", addr.AddrStr().c_str());
                break;
            }
            else
            {
                LOG(ERROR, "read error %s\n", addr.AddrStr().c_str());
                break;
            }
        }
    }

private:
    std::set<std::string>_safe_command;
};